#include "exceptions.h"
#include "date_time.h"
#include "logger.h"
#include "converter.h"

//! A struct containing the exception type and the detailed information about each exception
struct detailed_exception_information {
  const exception_type type;
  const char * const information;
};

// a global variable, which describes all kinds of exceptions
detailed_exception_information exception_information[] = {
  { INDEX_EXCEPTION, "Index out of range" },
  { DB_EXCEPTION, "Database failure" },
  { PARAMETER_EXCEPTION, "Invalid parameter or number of parameters don't match or they cannot be converted" },
  { SQL_INJECTION_EXCEPTION, "SQL injection detected" },
  { POINTER_EXCEPTION, "Pointer not set or null pointer" },
  { FILE_EXCEPTION, "File IO exception while reading or writing" },
  { NOT_ENOUGH_INFO_EXCEPTION, "Not enough information is provided, the operation will be canceled" },
  { OPERATION_NOT_ALLOWED_EXCEPTION, "Operation is not allowed" },
  { SOCKET_EXCEPTION, "Error while communicating with network ports using socket" },
  { INI_PARSER_EXCEPTION, "Error while parsing the ini file" },
  { XML_PARSER_EXCEPTION, "Error while parsing the XML file" },
  { NOT_SUPPORTED_EXCEPTION, "The operation is not supported" },
  { THREAD_EXCEPTION, "Thread exception" },
};

bool general_exception::logging_activated = true;

void general_exception::activate_exception_logging(bool b) {
  logging_activated = b;
} // general_exception::activate_exception_logging

const char *general_exception::get_message() const {
  return exception_information[type].information;
} // general_exception::get_message

const char *general_exception::get_file_name() const {
  return file_name;
} // general_exception::get_file_name

unsigned int general_exception::get_line() const {
  return line;
} // general_exception::get_line

const string &general_exception::get_info() const {
  return info;
} // general_exception::get_info

exception_type general_exception::get_type() const {
  return type;
} // general_exception::get_type

general_exception::general_exception(const char *file_name, unsigned int line, const string &info, exception_type type) : info(info), file_name(file_name), line(line), type(type) {
  if (logging_activated == true) {
    string str_cnv;
    converter::to_string(line, str_cnv);

    #pragma omp critical
    {
      const string d = date_time().to_string(); // date
      const string t = date_time().to_string(TIME_FORMAT); // time

      logger::log("exceptions_" + d + ".txt", t + " [" + get_message() + "] " + info);
      logger::log("exceptions_" + d + ".txt", string("file: ") + file_name);
      logger::log("exceptions_" + d + ".txt", "line: " + str_cnv);
    }

  } // if
} // general_exception::general_exception

general_exception::~general_exception() {
  // nothing to do
} // general_exception::~general_exception
